////////////////////////////////////////////////////////////////////////////////
// Copyright 2006 CORE Solutions Limited
// All rights reserved.
// PROPRIETARY AND CONFIDENTIAL INFORMATION.
// Use is subject to license terms.
//
// FUNCTION ID      :   
// AUTHOR           :   
// DATE CREATE      :   
// DESCRIPTION      :   
//                  :   
//                  :   
//                  :   
//
// MODIFICATION HISTORY:
// DATE         AUTHOR          VERSION NO.         COMMENT
// -----------  --------------  ------------------  -------------------
// 2006/04/26   Ric Yik         1.0                 BugZilla #5587
// 2006/05/11   Ric Yik         1.0                 BugZilla #5534
// 2006/05/17   Ric Yik         1.0                 BugZilla #5796
//
////////////////////////////////////////////////////////////////////////////////

package com.erp.framework.controller.action;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.erp.app.admin.menuObjectLabel.criteria.MenuObjectLabelSrchCriteria;
import com.erp.app.admin.menuObjectLabel.vo.MenuObjectLabelVo;
import com.erp.app.util.web.WebUtil;
import com.erp.framework.SimpleConstants;
import com.erp.framework.controller.form.MultiRow;
import com.erp.framework.controller.form.SimpleCoreForm;
import com.erp.framework.controller.form.SimplePageEditStyleForm;
import com.erp.framework.model.delegate.SimplePageEditStyleDelegate;
import com.erp.framework.model.schema.MetaData;
import com.erp.framework.model.schema.TableSchema;
import com.erp.framework.model.vo.SimpleBaseVo;
import com.erp.framework.util.CommonUtil;
import com.erp.framework.util.logger.Logger;
import com.erp.framework.util.mainmenu.MenuGroup;
import com.erp.framework.util.mainmenu.MenuObject;
import com.erp.framework.util.user.User;

public abstract class SimpleCoreAction extends SimpleBaseAction {

	// NOT intended to be overridden by subclasses
	protected final ActionForward coreExecute(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
			HttpServletResponse response) throws ServletException {

		ActionForward actionForward = null;
		try {
			HttpSession session = request.getSession(false);
			ActionErrors errors = new CustomActionErrors(new ActionErrors());
			SimpleCoreForm form = (SimpleCoreForm) formIn;
			actionForward = null;

			User editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);

			if (!(mapping.getName().equals(SimpleConstants.LOGIN_FORM_BEAN_NAME) || mapping.getName().equals(
					SimpleConstants.DEBUG_FORM_BEAN_NAME))
					|| mapping.getName().equals(SimpleConstants.LOG_LEVEL_FORM_BEAN_NAME)) {

				Logger.debug(this, "coreExecute(), hasLogin?" + (hasLogin(request)));

				// check login status
				if (!hasLogin(request)) {
					actionForward = mapping.findForward("logout");
					actionForward.setRedirect(true);
					setHandled(request);
				} else {
					// if has login, check accessibility
					String moduleName = getModuleName(mapping, form, request, response);
					Logger.debug(this, "coreExecute(), hasAccessRight?"
							+ editingUser.hasAccessRight(editingUser.getCompanyCode(), editingUser.getUserId(), moduleName));

					if (!editingUser.hasAccessRight(editingUser.getCompanyCode(), editingUser.getUserId(), moduleName)) {
						if (MOD_MAIN_MENU.equals(moduleName)) {
							actionForward = new ActionForward("/jsp/app/login/login.jsp");
							errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.access.main_menu"));
							saveErrors(request, errors);
						} else
							actionForward = mapping.findForward("default");
						setHandled(request);
					}

					// below is the original code
					// String moduleName = getModuleName(mapping, formIn,
					// request, response);
					// Logger.debug(this, "coreExecute(), hasAccessRight?"
					// +
					// editingUser.hasAccessRight(editingUser.getCompanyCode(),
					// editingUser.getUserId(),
					// moduleName));
					//
					// if
					// (!editingUser.hasAccessRight(editingUser.getCompanyCode(),
					// editingUser.getUserId(), moduleName)) {
					// actionForward = mapping.findForward("default");
					// setHandled(request);
					// }

                    if (!SimpleConstants.GENERIC_YES.equals(request.getParameter(SimpleConstants.REQUEST_PARAM_SKIP_MD))) {
    					// Get Menu Group List
    					if (!isHandled(request)) {
    						ArrayList menuGroupList = new ArrayList();
    						MenuGroup menuGroup = new MenuGroup();
    
    						menuGroupList = menuGroup.getMenuGroupList(editingUser.getCompanyCode(), editingUser.getUserId(),
    								moduleName);
    
    						if (menuGroupList == null) {
    							Logger.debug(this, "coreExecute(), menuGroupList is null");
    						} else {
    							form.setMenuGroupList(menuGroupList);
    						}
    					}

    					// Get Menu Object List (e.g. button)
    					if (!isHandled(request)) {
    						ArrayList menuObjectList = new ArrayList();
    						MenuObject menuObject = new MenuObject();
    						menuObjectList = menuObject.getMenuObjectList(editingUser.getCompanyCode(), editingUser.getUserId(),
    								moduleName);
    						if (menuObjectList == null) {
    							Logger.debug(this, "coreExecute(), menuObjectList is null");
    						} else {
    							form.setMenuObjectList(menuObjectList);
    						}
    					}
                    }

					String langCode = (String)session.getAttribute(SESSION_SYSTEM_LANG);
//					String moduleName = this.getModuleName(mapping, formIn, request, response);
					form.setSysLangCode(langCode);
					form.setModuleName(moduleName);
					
					String formReadOnly = CommonUtil.nullToString((String)session.getAttribute(getSimpleFormReadOnlySessionName()));
					session.removeAttribute(getSimpleFormReadOnlySessionName());
					if( (!CommonUtil.isEmpty(formReadOnly)) && (GENERIC_YES.equals(formReadOnly)) ){
						form.setIsReadOnly(GENERIC_YES);
					}
					
					String roCaller = CommonUtil.nullToString((String) session.getAttribute(getSimpleFormReadOnlyCallerSessionName()));
					session.removeAttribute(getSimpleFormReadOnlyCallerSessionName());
					if( (!CommonUtil.isEmpty(roCaller)) ) {
						form.setRoCaller(roCaller);
					}
				}

			}

			Logger.debug(this, "coreExecute(), actionForward is null =[" + (actionForward == null) + "]");
			if (actionForward != null) {
				Logger.debug(this, "coreExecute(), actionForward=[" + actionForward.getPath() + "]");
			}
		} catch (Exception e) {
			Logger.logExceptions(this, e);
		}
		return actionForward;
	}

	public String getSimpleFormReadOnlySessionName(){
		return SESSION_SIMPLE_FORM_READ_ONLY_SESSION_NAME;
	}
	
	public String getSimpleFormReadOnlyCallerSessionName(){
		return SESSION_SIMPLE_FORM_READ_ONLY_CALLER_SESSION_NAME;
	}
	
	protected boolean hasLogin(HttpServletRequest request) {

		HttpSession session = request.getSession(false);
		User editingUser = null;
		if (session == null)
			return false;
		else {
			editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);
			return (editingUser != null);
		}
	}

	protected abstract String getModuleName(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
			HttpServletResponse response);

	protected Class getMasterVOClass() {
		return null;
	}

//	protected void copyTsFromVoToForm(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
//	        HttpServletResponse response, SimpleBaseVo bizModel) throws Exception {    
//    }

	protected void copyTsFromVoToForm(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
			HttpServletResponse response, SimpleBaseVo bizModel) throws Exception {
        if (SimpleConstants.GENERIC_YES.equals(request.getParameter(SimpleConstants.REQUEST_PARAM_SKIP_MD))) {
            return;
        }
		try {
			SimpleCoreForm form = (SimpleCoreForm) formIn;
			HttpSession session = request.getSession(false);
			User editingUser = (User) session.getAttribute(SimpleConstants.SESSION_USER);

			// that means this form does not need a schema class
			if (getMasterVOClass() == null) {
				return;
			}

			if (bizModel == null) {
				bizModel = (SimpleBaseVo) getMasterVOClass().newInstance();
			}

			if (bizModel.getTableSchemaType() != null) {
				form.setTs((TableSchema) bizModel.getTableSchemaType().newInstance());
			}
			if (bizModel.getTableSchemaName() != null) {
				form.setTsName(bizModel.getTableSchemaName());
			}
			if (bizModel.getChildTableSchemaTypes() != null) {
				Class[] childTableSchemaTypes = bizModel.getChildTableSchemaTypes();
				TableSchema[] childTableSchemas = new TableSchema[0];
                childTableSchemas = new TableSchema[childTableSchemaTypes.length];
				for (int k = 0; k < childTableSchemaTypes.length; k++) {
					childTableSchemas[k] = (TableSchema) childTableSchemaTypes[k].newInstance();
                    List rows = form.getMultiRows(k);
                    if (rows != null) {
                        for (int i = 0; i < rows.size(); ++i) {
                            MultiRow row = (MultiRow) rows.get(i);
                            row.setTs(childTableSchemas[k]);
                            row.setTsName(childTableSchemaTypes[k].getName());
                        }
                    }
				}
				form.setChildTs(childTableSchemas);
			} else if (form instanceof SimplePageEditStyleForm) {
                List rows = form.getMultiRows(0);
                for (int i = 0; i < rows.size(); ++i) {
                    MultiRow row = (MultiRow) rows.get(i);
                    row.setTs(form.getTs());
                    row.setTsName(form.getTsName());
                }
            }
			if (bizModel.getChildTableSchemaNames() != null) {
				form.setChildTsNames(bizModel.getChildTableSchemaNames());
			}

			SimplePageEditStyleDelegate pedg = new SimplePageEditStyleDelegate();
			MenuObjectLabelSrchCriteria crit = new MenuObjectLabelSrchCriteria();

			crit.setSrchCompanyCode(editingUser.getCompanyCode());
			crit.setSrchGroupIdFr(getSimpleSrchGroupId());
			crit.setSrchGroupIdTo(getSimpleSrchGroupId());
			crit.setSrchMenuIdFr(getSimpleSrchMenuId(mapping, formIn, request, response));
			crit.setSrchMenuIdTo(getSimpleSrchMenuId(mapping, formIn, request, response));
			crit.setSrchObjectTypeFr(getSimpleSrchObjectType());
			crit.setSrchObjectTypeTo(getSimpleSrchObjectType());
			String sysLangSetting = WebUtil.getPrjParamVal(session, PP_SYS_LANG_SETTING);
			if (SYS_LANG_SET_BY_OS.equals(sysLangSetting)) {
				crit.setSrchLangCodeFr(CommonUtil.nullToString(session.getAttribute(SESSION_SYSTEM_LANG)));
				crit.setSrchLangCodeTo(CommonUtil.nullToString(session.getAttribute(SESSION_SYSTEM_LANG)));
			} else {
				String sysLang = (String)session.getAttribute(SESSION_SYSTEM_LANG);
				crit.setSrchLangCodeFr(CommonUtil.nullToString(sysLang));
				crit.setSrchLangCodeTo(CommonUtil.nullToString(sysLang));
			}

			ArrayList menuObjectLabelVoList = (ArrayList) pedg.findByCriteria(new MenuObjectLabelVo(), crit);
			Logger.debug(this, "copyTsFromVoToForm(), size of menuObjectLabelVoList: " + menuObjectLabelVoList.size());

			TableSchema ts = form.getTs();
			Logger.debug(this, "copyTsFromVoToForm(), ts is null?" + (ts == null));
            if(ts == null){
                //currently return out, but need to throw exceptions to enforce all modules have schema
                Logger.debug(this, "copyTsFromVoToForm(), this form[" + form.getClass().getName() + "] does not have a header schema"); 
                return;
            }
            
			ArrayList metadataList = ts.getTs();
            Logger.debug(this, "copyTsFromVoToForm(), size of hdr metadataList: " + (metadataList.size()));
            
			for (int j = 0; (metadataList != null) && (j < metadataList.size()); j++) {
				MetaData md = (MetaData) metadataList.get(j);
				String mdWebObjectId = CommonUtil.nullToString(md.getWebObjectId());
				for (int i = 0; (menuObjectLabelVoList != null) && (i < menuObjectLabelVoList.size()); i++) {
					MenuObjectLabelVo vo = (MenuObjectLabelVo) menuObjectLabelVoList.get(i);
					String objectId = vo.getObjectId();
					String objectWebLabel = vo.getObjectWebLabel();
					int textSize = (vo.getTextSize() == null) ? 0 : vo.getTextSize().intValue();
					int textMaxLen = (vo.getTextMaxLen() == null) ? 0 : vo.getTextMaxLen().intValue();
					int taColSize = (vo.getTaColSize() == null) ? 0 : vo.getTaColSize().intValue();
					int taRowSize = (vo.getTaRowSize() == null) ? 0 : vo.getTaRowSize().intValue();

//					Logger.field(this, "copyTsFromVoToForm(), objectId=" + objectId);
//					Logger.field(this, "copyTsFromVoToForm(), objectWebLabel=" + objectWebLabel);

					if (mdWebObjectId.equals(objectId)) {
                        Logger.field(this, "copyTsFromVoToForm(), MATCH!, ts mdWebObjectId=" + mdWebObjectId);                       
						md.setWebLabelName(objectWebLabel);
                        md.setColumnSize(textMaxLen);
                        md.setDisplaySize(textSize);
						md.setTextAreaColSize(taColSize);
						md.setTextAreaRowSize(taRowSize);                        
					}
				}
			}

            //no need for child, child table schema is the same as header table schema
            if (form instanceof SimplePageEditStyleForm){
                return;
            }
            
			TableSchema[] childTs = form.getChildTs();
            Logger.debug(this, "copyTsFromVoToForm(), childTs is null?" + (childTs == null));
            if(childTs == null){
                //currently return out, but need to throw exceptions to enforce all modules have schema
                Logger.warn(this, "copyTsFromVoToForm(), this form[" + form.getClass().getName() + "] does not have any child schema");
                return;
            }
            Logger.debug(this, "copyTsFromVoToForm(), how many child? childTs.size(): " + (childTs.length));
            
			for (int k = 0; (childTs != null) && (k < childTs.length); k++) {
				TableSchema cTs = childTs[k];
				ArrayList childMetadataList = cTs.getTs();
                Logger.debug(this, "copyTsFromVoToForm(), size of child[" + k + "] childMetadataList: " 
                		+ (childMetadataList.size()));
				for (int m = 0; (childMetadataList != null) && (m < childMetadataList.size()); m++) {
					MetaData md = (MetaData) childMetadataList.get(m);
					String mdWebObjectId = CommonUtil.nullToString(md.getWebObjectId());

					for (int i = 0; (menuObjectLabelVoList != null) && (i < menuObjectLabelVoList.size()); i++) {
						MenuObjectLabelVo vo = (MenuObjectLabelVo) menuObjectLabelVoList.get(i);
						String objectId = vo.getObjectId();
						String objectWebLabel = vo.getObjectWebLabel();
						int textSize = (vo.getTextSize() == null) ? 0 : vo.getTextSize().intValue();
						int textMaxLen = (vo.getTextMaxLen() == null) ? 0 : vo.getTextMaxLen().intValue();
						int taColSize = (vo.getTaColSize() == null) ? 0 : vo.getTaColSize().intValue();
						int taRowSize = (vo.getTaRowSize() == null) ? 0 : vo.getTaRowSize().intValue();

//						Logger.field(this, "copyTsFromVoToForm(), objectId=" + objectId);
//						Logger.field(this, "copyTsFromVoToForm(), objectWebLabel=" + objectWebLabel);

						if (mdWebObjectId.equals(objectId)) {
                            Logger.field(this, "copyTsFromVoToForm(), MATCH! dtl ts mdWebObjectId=" + mdWebObjectId);                            
							md.setWebLabelName(objectWebLabel);
							md.setColumnSize(textMaxLen);
							md.setDisplaySize(textSize);
							md.setTextAreaColSize(taColSize);
							md.setTextAreaRowSize(taRowSize);
						}
					}
				}
			}
		} catch (Exception e) {
			Logger.logExceptions(this, e);
		}
	}

	protected String getSimpleSrchGroupId() {
		return DBMENU_GENERAL_MENU;
	}

	protected String getSimpleSrchObjectType() {
		return DBMENU_OBJECT_TYPE_LABEL;
	}

	// must set to abstract later.
	protected String getSimpleSrchMenuId() {
		return "";
	}
	
	// 2006-01-19 to have more flexability to handle multiple modules sharing the same set of search and maintenace.
	protected String getSimpleSrchMenuId(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
			HttpServletResponse response) {
		
		return getSimpleSrchMenuId();
	}

    // handlers for pagination.

    protected ActionForward processActionScrollLeft(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleCoreForm form = (SimpleCoreForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            int sidx = form.getSidx();

            sidx -= SimpleConstants.MAX_DISPLAY;

            if (sidx < 0)
                sidx = 0;
            if (sidx > form.getMultiRows().size() - 1)
                sidx = form.getMultiRows().size() - 1;

            form.setSidx(sidx);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.general", e.toString()));
            Logger.logExceptions(this, e);
        }
        return actionForward;
    }

    protected ActionForward processActionScrollRight(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {

        ActionForward actionForward = null;
        try {
            SimpleCoreForm form = (SimpleCoreForm) formIn;
            HttpSession session = request.getSession(false);

            actionForward = new ActionForward(mapping.getInput());

            int sidx = form.getSidx();

            sidx += SimpleConstants.MAX_DISPLAY;

            if (sidx < 0)
                sidx = 0;
            if (sidx > form.getMultiRows().size() - 1)
                sidx = form.getMultiRows().size() - 1;

            form.setSidx(sidx);
        } catch (Exception e) {
            errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("exception.general", e.toString()));
            Logger.logExceptions(this, e);
        }
        return actionForward;
    }

    protected ActionForward processActionScrollToFirstPage(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
        ActionForward actionForward = new ActionForward(mapping.getInput());
        SimpleCoreForm form = (SimpleCoreForm) formIn;

        form.setSidx(0);

        return actionForward;
    }

    protected ActionForward processActionScrollToLastPage(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
        ActionForward actionForward = new ActionForward(mapping.getInput());
        SimpleCoreForm form = (SimpleCoreForm) formIn;

        form.setSidx(Integer.parseInt(form.getLastPageSidx()));

        return actionForward;
    }

    protected ActionForward processActionScrollTo(ActionMapping mapping, ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
        ActionForward actionForward = new ActionForward(mapping.getInput());
        SimpleCoreForm form = (SimpleCoreForm) formIn;

        String scrollTo = form.getScrollTo();
        int page = 0;

        try {
            page = Integer.parseInt(scrollTo);
        } catch (NumberFormatException e) {
            page = form.getCurrentPage();
        }

        if (page < 1)
            page = 1;

        if (page > form.getTotalPage())
            page = form.getTotalPage();

        form.setSidx((page - 1) * MAX_DISPLAY);

        return actionForward;
    }

}